package com.aquarium.module;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import android.R.integer;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.aquarium.R;
import com.aquarium.alias.AliasManager;
import com.aquarium.bt.BTManager;
import com.aquarium.bt.DataInterpreter;
import com.aquarium.bt.DataStruct;
import com.aquarium.config.BTCommand;
import com.aquarium.config.ModuleName;
import com.aquarium.util.SPUtils;

public class ModuleController implements Observer {

	public final static int MESSAGE_COMMAND_REPLY = 1;

	private final static String PREFER_NAME = "module_control";

	private final static String PREFER_KEY_WATER_MOTOR_MODE = "WATER_MOTOR_MODE";
	private final static String PREFER_KEY_WATER_MOTOR_ON = "PREFER_WATER_MOTOR_ON";
	private final static String PREFER_KEY_PROTEIN_SKIMMER_MODE = "PROTEIN_SKIMMER_MODE";
	private final static String PREFER_KEY_PROTEIN_SKIMMER_ON = "PROTEIN_SKIMMER_ON";
	public final static String PREFER_VALUE_MODULE_AUTO = "AUTO";
	public final static String PREFER_VALUE_MODULE_MANU = "MANU";
	private final static String PREFER_KEY_WAVE_MOTOR_1_MODE = "PREFER_KEY_WAVE_MOTOR_1_MODE";
	private final static String PREFER_KEY_WAVE_MOTOR_2_MODE = "PREFER_KEY_WAVE_MOTOR_2_MODE";
	private final static String PREFER_KEY_WAVE_MOTOR_1_ON = "PREFER_KEY_WAVE_MOTOR_1_ON";
	private final static String PREFER_KEY_WAVE_MOTOR_2_ON = "PREFER_KEY_WAVE_MOTOR_2_ON";

	private static Context mContext;
	private static ModuleController mModuleController;
	private AliasManager mAliasManager;
	private BTManager mBTManager;

	private DataStruct mPendingCmd;
	private Handler mPendingHandler;

	protected SharedPreferences mModuleSettingPreferences;

	public static String MODULE_NULL = "";

	protected ModuleController() {
		mBTManager = BTManager.getInstance();
		mBTManager.init(mContext.getApplicationContext());
		mBTManager.addObservers(this);
		mAliasManager = AliasManager.getInstance(mContext);
		mModuleSettingPreferences = mContext.getSharedPreferences(PREFER_NAME,
				Context.MODE_PRIVATE);

	}

	public static ModuleController getInstance(Context c) {
		if (mModuleController == null) {
			mContext = c;
			mModuleController = new ModuleController();
		}
		return mModuleController;
	}

	public ArrayList<String> getConnectedModules() {
		ArrayList<String> modules = new ArrayList<String>();
		int[] selectedId = mAliasManager.getControllerType();
		String[] moduleNames = mContext.getResources().getStringArray(
				R.array.controllers_array);
		for (int i = 0; i < selectedId.length; i++) {
			if (selectedId[i] >= moduleNames.length) {
				continue;
			}
			String moduleName = moduleNames[selectedId[i]];
			if (moduleName.equals(ModuleName.WATER_MOTOR)) {
				modules.add(ModuleName.WATER_MOTOR);
			} else if (moduleName.equals(ModuleName.PROTEIN_SIMMMER)) {
				modules.add(ModuleName.PROTEIN_SIMMMER);
			} else if (moduleName.equals(ModuleName.UV_LIGHT)) {
				modules.add(ModuleName.UV_LIGHT);
			} else if (moduleName.equals(ModuleName.DOSING_PUMP)) {
				modules.add(ModuleName.DOSING_PUMP);
			} else if (moduleName.equals(ModuleName.WAVE_MOTOR_1)) {
				modules.add(ModuleName.WAVE_MOTOR_1);
			} else if (moduleName.equals(ModuleName.WAVE_MOTOR_2)) {
				modules.add(ModuleName.WAVE_MOTOR_2);
			}
		}
		return modules;
	}

	public void sendModuleOnOffCommand(String moduleName, boolean isOn,
			boolean isPending, Handler handler) {
		int controllerId = mAliasManager.getControllerPosition(moduleName);
//		byte[] cmd = getCommand(controllerId, isOn);
	//modify 2013.7.27	
		byte[] cmd=BTCommand.getModuleOnOffCommand(controllerId, moduleName, 0, isOn);
		DataStruct unpackCmd = DataInterpreter.unpack(cmd);
		for (int i = 0; i < cmd.length; i++) {
			Log.d("sendmoduleTAG", "data:" + Integer.toHexString(cmd[i] & 0xFF));
		}
		if (isPending && handler != null) {
			setPendingCommand(unpackCmd, handler);
		}
		mBTManager.sendData(unpackCmd);
	}

	public void sendDosingPumpCommand(String moduleName, int pumpID, int volumn) {
		int controllerId = mAliasManager.getControllerPosition(moduleName);
		byte[] cmd = BTCommand.getDosingPumpCommand(controllerId, pumpID, volumn);
		DataStruct unpackCmd = DataInterpreter.unpack(cmd);
		for (int i = 0; i < cmd.length; i++) {
			Log.d("sendDosingPumpCommand", "data:" + Integer.toHexString(cmd[i] & 0xFF));
		}
		mBTManager.sendData(unpackCmd);
	}

	public void sendWaveMotorCommand(String moduleName, int motorId,
			int waveType, boolean isPending, Handler handler) {
		int controllerId = mAliasManager.getControllerPosition(moduleName);
		byte[] cmd = BTCommand.getWaveMotorOnOffCommand(controllerId, motorId,
				waveType);
		DataStruct unpackCmd = DataInterpreter.unpack(cmd);
		if (isPending && handler != null) {
			setPendingCommand(unpackCmd, handler);
		}
		for (int i = 0; i < cmd.length; i++) {
			Log.d("sendWaveMotorCommand", "data:" + Integer.toHexString(cmd[i] & 0xFF));
		}
		mBTManager.sendData(unpackCmd);
	}

	private byte[] getCommand(int controllerId, boolean isOn) {
		switch (controllerId) {
		case 1:
			if (isOn) {
				return BTCommand.AC_SW_O1_ON;
			} else {
				return BTCommand.AC_SW_O1_OFF;
			}
		case 2:
			if (isOn) {
				return BTCommand.AC_SW_O2_ON;
			} else {
				return BTCommand.AC_SW_O2_OFF;
			}
		case 3:
			if (isOn) {
				return BTCommand.AC_SW_O3_ON;
			} else {
				return BTCommand.AC_SW_O3_OFF;
			}
		case 4:
			if (isOn) {
				return BTCommand.AC_SW_O4_ON;
			} else {
				return BTCommand.AC_SW_O4_OFF;
			}
		case 5:
			if (isOn) {
				return BTCommand.AC_SW_O5_ON;
			} else {
				return BTCommand.AC_SW_O5_OFF;
			}
		case 6:
			if (isOn) {
				return BTCommand.AC_SW_O6_ON;
			} else {
				return BTCommand.AC_SW_O6_OFF;
			}
		default:
			return null;
		}
	}

	public void setPendingCommand(DataStruct dataStruct, Handler handler) {
		mPendingCmd = dataStruct;
		mPendingHandler = handler;
	}

	@Override
	public void update(Observable observable, Object data) {
		if (observable instanceof BTManager) {
			if (mPendingCmd != null) {
				if ((((DataStruct) data).code) == mPendingCmd.code
						&& mPendingHandler != null) {

					Message msg = new Message();
					msg.what = MESSAGE_COMMAND_REPLY;
					msg.obj = data;
					mPendingHandler.sendMessage(msg);
					mPendingCmd = null;
					mPendingHandler = null;
				}
			}
		}
	}

	public void setWaterMotorMode(String mode) {
		if (PREFER_VALUE_MODULE_AUTO.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(),
					PREFER_KEY_WATER_MOTOR_MODE, PREFER_VALUE_MODULE_AUTO);
		} else if (PREFER_VALUE_MODULE_MANU.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(),
					PREFER_KEY_WATER_MOTOR_MODE, PREFER_VALUE_MODULE_MANU);
		}
	}

	public String getWaterMotorMode() {
		return SPUtils.getSP(mModuleSettingPreferences,
				PREFER_KEY_WATER_MOTOR_MODE, PREFER_VALUE_MODULE_MANU);
	}

	public void setWaterMotorOnOff(boolean isOn) {
		SPUtils.setSP(mModuleSettingPreferences.edit(),
				PREFER_KEY_WATER_MOTOR_ON, isOn);
	}

	public void setWaveMotorMode(int waveMotorIndex, String mode) {
		String key = "";
		if (waveMotorIndex == 1) {
			key = PREFER_KEY_WAVE_MOTOR_1_MODE;
		} else if (waveMotorIndex == 2) {
			key = PREFER_KEY_WAVE_MOTOR_2_MODE;
		} else {
			return;
		}

		if (PREFER_VALUE_MODULE_AUTO.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(), key,
					PREFER_VALUE_MODULE_AUTO);
		} else if (PREFER_VALUE_MODULE_MANU.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(), key,
					PREFER_VALUE_MODULE_MANU);
		}
	}

	public String getWaveMotorMode(int waveMotorIndex) {
		String key = "";
		if (waveMotorIndex == 1) {
			key = PREFER_KEY_WAVE_MOTOR_1_MODE;
		} else if (waveMotorIndex == 2) {
			key = PREFER_KEY_WAVE_MOTOR_2_MODE;
		} else {
			return key;
		}
		return SPUtils.getSP(mModuleSettingPreferences, key,
				PREFER_VALUE_MODULE_MANU);
	}

	public boolean isWaveMotorOn(int waveMotorIndex) {
		String key = "";
		if (waveMotorIndex == 1) {
			key = PREFER_KEY_WAVE_MOTOR_1_ON;
		} else if (waveMotorIndex == 2) {
			key = PREFER_KEY_WAVE_MOTOR_2_ON;
		} else {
			return false;
		}
		return SPUtils.getSP(mModuleSettingPreferences, key, false);
	}

	public void setWaveMotorOnOff(int waveMotorIndex, boolean isOn) {
		String key = "";
		if (waveMotorIndex == 1) {
			key = PREFER_KEY_WAVE_MOTOR_1_ON;
		} else if (waveMotorIndex == 2) {
			key = PREFER_KEY_WAVE_MOTOR_2_ON;
		} else {
			return;
		}
		SPUtils.setSP(mModuleSettingPreferences.edit(), key, isOn);
	}

	public boolean isWaterMotorOn() {
		return SPUtils.getSP(mModuleSettingPreferences,
				PREFER_KEY_WATER_MOTOR_ON, false);
	}

	public void setProteinSkimmerMode(String mode) {
		if (PREFER_VALUE_MODULE_AUTO.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(),
					PREFER_KEY_PROTEIN_SKIMMER_MODE, PREFER_VALUE_MODULE_AUTO);
		} else if (PREFER_VALUE_MODULE_MANU.equals(mode)) {
			SPUtils.setSP(mModuleSettingPreferences.edit(),
					PREFER_KEY_PROTEIN_SKIMMER_MODE, PREFER_VALUE_MODULE_MANU);
		}
	}

	public String getProteinSkimmerMode() {
		return SPUtils.getSP(mModuleSettingPreferences,
				PREFER_KEY_PROTEIN_SKIMMER_MODE, PREFER_VALUE_MODULE_MANU);
	}

	public void setProteinSkimmerOnOff(boolean isOn) {
		SPUtils.setSP(mModuleSettingPreferences.edit(),
				PREFER_KEY_PROTEIN_SKIMMER_ON, isOn);
	}

	public boolean isProteinSkimmerOn() {
		return SPUtils.getSP(mModuleSettingPreferences,
				PREFER_KEY_PROTEIN_SKIMMER_ON, false);
	}

	public void setModuleMode(String moduleName, String mode) {
		if (ModuleName.WATER_MOTOR.equals(moduleName)) {
			setWaterMotorMode(mode);
		} else if (ModuleName.PROTEIN_SIMMMER.equals(moduleName)) {
			setProteinSkimmerMode(mode);
		} else if (ModuleName.WAVE_MOTOR_1.equals(moduleName)) {
			setWaveMotorMode(1, mode);
		} else if (ModuleName.WAVE_MOTOR_2.equals(moduleName)) {
			setWaveMotorMode(2, mode);
		}
	}
}
